package thread.ABC;


public class ABCDemo implements Runnable{
    private Object self;
    private Object pre;
    private String symbol;
    private Integer n=10;
    public ABCDemo(String name){
        this.symbol=name;
    }

    public ABCDemo(Object self, Object pre, String symbol) {
        this.self = self;
        this.pre = pre;
        this.symbol = symbol;
    }

    public static void main(String[] args) throws InterruptedException {
        //3个线程交替打印ABC
        Object A=new String("A");
        Object B=new String("B");
        Object C=new String("C");
        Thread a= new Thread(new ABCDemo(A,C,"A"));
        Thread b= new Thread(new ABCDemo(B, A,"B"));
        Thread c= new Thread(new ABCDemo(C,B,"C"));
        a.setName("线程a");
        b.setName("线程b");
        c.setName("线程c");

        a.start();
        Thread.sleep(100);
        b.start();
        Thread.sleep(100);
        c.start();

        //a线程进入，持有C和A锁
        //b线程此时假设已经启动，需要有A锁才能进入，但是被a线程占用着，进入等待状态
        //c线程启动，需要B锁,B锁没有被占用，可以直接进入，但是需要的C锁被占用，
        // a线程执行完毕后释放A锁，先随机唤醒A对象等待池中的b线程
        //此时a线程释放了C锁，正好,c线程有了C锁可以执行
    }

    @Override
    public void run() {

        while((n--)>0){
            synchronized (pre){
                System.out.println(Thread.currentThread().getName()+"拥有"+pre.toString()+"锁");
                synchronized (self){
                    System.out.println(Thread.currentThread().getName()+"拥有"+self.toString()+"锁");
                    System.out.println(Thread.currentThread().getName()+"---------------------------"+symbol);
                    //假设要执行1秒

                    self.notifyAll();
                    System.out.println(Thread.currentThread().getName()+"随机唤醒"+self.toString()+"锁等待池中的一个线程");
                }
                System.out.println(Thread.currentThread().getName()+"释放"+self.toString()+"锁");

                try {
                    pre.wait();
                    System.out.println(Thread.currentThread().getName()+"释放"+pre.toString()+"锁");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }
}
